const { exec } = require('child_process');
const { logger } = require("ee-core/log");
const si = require('systeminformation');
const os = require('os');
const DesCrypto = require("../utils/DesCrypto.js")
const regedit = require('regedit');

class ComputerService {
    cryptoKey = "4F420A92-6FD3-4644-ACB2-60A786B21979";
    getCPUId() {
        return new Promise((resolve, reject) => {
            if (os.platform() === 'win32') {
                // Windows
                exec('C:\\Windows\\System32\\wbem\\wmic.exe cpu get ProcessorId', (error, stdout) => {
                    if (error) return reject(error);
                    const lines = stdout.trim().split('\n');
                    resolve(lines.length > 1 ? lines[1].trim() : 'Unknown');
                });
            } else if (os.platform() === 'darwin') {
                // macOS
                exec('sysctl -n machdep.cpu.brand_string', (error, stdout) => {
                    if (error) return reject(error);
                    resolve(stdout.trim());
                });
            } else {
                // Linux
                exec("cat /proc/cpuinfo | grep 'processor\\|model name' | head -n 1", (error, stdout) => {
                    if (error) return reject(error);
                    resolve(stdout.trim().split(':')[1]?.trim() || 'Unknown');
                });
            }
        });
    }

    async getNewWork() {
        try {
            // 获取所有网络接口信息
            const interfaces = await si.networkInterfaces();

            // 根据不同平台执行相应命令获取路由表
            const routeTable = await new Promise((resolve, reject) => {
                const cmd = process.platform === 'win32'
                    ? 'route print'
                    : process.platform === 'darwin'
                        ? 'netstat -rn'
                        : 'ip route show';

                exec(cmd, (error, stdout) => {
                    if (error) reject(error);
                    else resolve(stdout);
                });
            });

            // 解析路由表获取默认网关
            let defaultGateway = null;

            if (process.platform === 'win32') {
                // Windows 路由表解析
                const lines = routeTable.split('\n');
                let inIPv4Section = false;

                for (const line of lines) {
                    if (line.includes('IPv4 Route Table')) {
                        inIPv4Section = true;
                        continue;
                    }

                    if (line.includes('IPv6 Route Table')) {
                        inIPv4Section = false;
                        continue;
                    }

                    if (inIPv4Section && line.trim().startsWith('0.0.0.0')) {
                        const parts = line.trim().split(/\s+/);
                        if (parts.length >= 3) {
                            defaultGateway = parts[2];
                            break;
                        }
                    }
                }
            } else if (process.platform === 'darwin') {
                // macOS 路由表解析
                const regex = /default\s+([^\s]+)\s+([^\s]+)/;
                const match = routeTable.match(regex);
                if (match) defaultGateway = match[1];
            } else {
                // Linux 路由表解析
                const regex = /default\s+via\s+([^\s]+)\s+dev\s+([^\s]+)/;
                const match = routeTable.match(regex);
                if (match) defaultGateway = match[1];
            }

            // 构建MAC地址到网关的映射
            const macToGateway = new Map();

            interfaces.forEach(iface => {
                // 优先使用网卡自身的gateway4字段
                let gateway = iface.gateway4;

                // 如果网卡没有指定网关，使用系统默认网关
                if (!gateway && defaultGateway) {
                    gateway = defaultGateway;
                }

                if (iface.mac && iface.mac !== '00:00:00:00:00:00') {
                    macToGateway.set(iface.mac, gateway || 'Unknown');
                }
            });

            return Object.fromEntries(macToGateway);
        } catch (error) {
            logger.error('获取网关信息时出错:', error);
            return {};
        }
    }

    getMacAddresses() {
        const interfaces = os.networkInterfaces();
        const macs = [];
        Object.keys(interfaces).forEach((ifname) => {
            interfaces[ifname].forEach((iface) => {
                if (!iface.internal && iface.mac !== '00:00:00:00:00:00') {
                    macs.push({
                        interface: ifname,
                        mac: iface.mac
                    });
                }
            });
        });

        return macs;
    }

    getDiskSerialNumber() {
        return new Promise((resolve, reject) => {
            if (os.platform() === 'win32') {
                // Windows
                exec('C:\\Windows\\System32\\wbem\\wmic.exe diskdrive get serialnumber', (error, stdout) => {
                    if (error) return reject(error);
                    const lines = stdout.trim().split('\n');
                    resolve(lines.length > 1 ? lines[1].trim() : 'Unknown');
                });
            } else if (os.platform() === 'darwin') {
                // macOS
                exec('diskutil info / | grep "Volume UUID"', (error, stdout) => {
                    if (error) return reject(error);
                    resolve(stdout.trim().split(':')[1]?.trim() || 'Unknown');
                });
            } else {
                // Linux (需要 root 权限)
                exec('hdparm -i /dev/sda | grep SerialNo', (error, stdout) => {
                    if (error) {
                        // 尝试 lsblk 命令
                        exec('lsblk -d -o NAME,SERIAL', (err, out) => {
                            if (err) return reject(err);
                            resolve(out.trim().split('\n')[1]?.split(/\s+/)[1] || 'Unknown');
                        });
                        return;
                    }
                    resolve(stdout.trim().split('=')[1]?.trim() || 'Unknown');
                });
            }
        });
    }


    getGatewayAddress() {
        return new Promise((resolve, reject) => {
            if (os.platform() === 'win32') {
                // Windows
                exec('route print', (error, stdout) => {
                    if (error) return reject(error);
                    const lines = stdout.split('\n');
                    const gatewayLine = lines.find(line =>
                        line.includes('0.0.0.0') &&
                        line.includes('0.0.0.0') &&
                        !line.includes('On-link')
                    );

                    if (gatewayLine) {
                        const parts = gatewayLine.trim().split(/\s+/);
                        resolve(parts[2] || 'Unknown');
                    } else {
                        resolve('Unknown');
                    }
                });
            } else {
                // Linux/macOS
                exec('ip route show default', (error, stdout) => {
                    if (error) {
                        // 备用命令
                        exec('netstat -rn | grep default', (err, out) => {
                            if (err) return reject(err);
                            const parts = out.trim().split(/\s+/);
                            resolve(parts[1] || 'Unknown');
                        });
                        return;
                    }

                    const parts = stdout.trim().split(' ');
                    const gatewayIndex = parts.indexOf('via');
                    resolve(gatewayIndex > -1 ? parts[gatewayIndex + 1] : 'Unknown');
                });
            }
        });
    }

    async getGatewayMacAddress(gateway) {
        try {
            if (!gateway) {
                gateway = await this.getGatewayAddress();
            }

            if (gateway === 'Unknown') {
                return 'Unknown';
            }

            return new Promise((resolve, reject) => {
                if (os.platform() === 'win32') {
                    // Windows
                    exec('C:\\Windows\\System32\\arp -a', (error, stdout) => {
                        if (error) return reject(error);
                        const lines = stdout.split('\n');
                        const gatewayLine = lines.find(line =>
                            line.includes(gateway) &&
                            !line.includes('incomplete')
                        );

                        if (gatewayLine) {
                            const parts = gatewayLine.trim().split(/\s+/);
                            resolve(parts[1] || 'Unknown');
                        } else {
                            resolve('Unknown');
                        }
                    });
                } else {
                    // Linux/macOS
                    exec(`arp -n ${gateway}`, (error, stdout) => {
                        if (error) {
                            // 备用命令
                            exec(`ip neighbor show ${gateway}`, (err, out) => {
                                if (err) return reject(err);
                                const parts = out.trim().split(' ');
                                const macIndex = parts.indexOf('lladdr');
                                resolve(macIndex > -1 ? parts[macIndex + 1] : 'Unknown');
                            });
                            return;
                        }

                        const parts = stdout.trim().split(/\s+/);
                        resolve(parts[2] || 'Unknown');
                    });
                }
            });
        } catch (error) {
            return 'Unknown';
        }
    }

    // 获取网关集（interface IP => gateway IP）
    getGatewayMap() {
        return new Promise((resolve, reject) => {
            if (os.platform() === "win32") {
                exec("C:\\Windows\\System32\\route print", (error, stdout) => {
                    if (error) return reject(`获取路由表失败: ${error.message}`);

                    const lines = stdout
                        .split("\n")
                        .filter(
                            (line) =>
                                /^\s*0\.0\.0\.0\s+0\.0\.0\.0/.test(line) &&
                                !line.includes("On-link")
                        );

                    const gatewayMap = {};
                    lines.forEach((line) => {
                        const parts = line.trim().split(/\s+/);
                        if (parts.length >= 4) {
                            const interfaceIp = parts[3];
                            const gatewayIp = parts[2];
                            if (interfaceIp && gatewayIp) {
                                gatewayMap[interfaceIp] = gatewayIp;
                            }
                        }
                    });

                    resolve(gatewayMap);
                });
            } else {
                exec("ip route show default", (error, stdout) => {
                    if (!error && stdout) {
                        const parts = stdout.trim().split(" ");
                        const gatewayIndex = parts.indexOf("via");
                        const gateway = gatewayIndex > -1 ? parts[gatewayIndex + 1] : null;
                        return resolve(gateway ? { [gateway]: gateway } : {});
                    }

                    exec("netstat -rn | grep default", (err, out) => {
                        if (err) return reject(`获取默认路由失败: ${err.message}`);
                        const parts = out.trim().split(/\s+/);
                        const gateway = parts[1];
                        resolve(gateway ? { [gateway]: gateway } : {});
                    });
                });
            }
        });
    }
    // 获取 MAC 地址和描述信息
    getMacAddressAndDescriptionMap() {
        return new Promise((resolve, reject) => {
            if (os.platform() !== "win32") {
                return resolve([]); // 非 Windows 平台返回空数组
            }

            exec("C:\\Windows\\System32\\route print", (error, stdout) => {
                if (error) return reject(`获取路由表失败: ${error.message}`);


                const lines = stdout.split("\n");


                // 转换为 MAC:Description 的 Map 结构
                const macDescMap = lines.reduce((acc, line) => {
                    const match = /^(\d+)\.\.\.([0-9a-fA-F ]{17})\s+\.+([\s\S]*)$/.exec(line.trim());
                    if (match) {
                        const [, , mac, description] = match;
                        const formattedMac = mac.trim().replace(/ /g, ":");
                        acc[formattedMac] = description.trim();
                    }
                    return acc;
                }, {});
                resolve(macDescMap);
            });
        });
    }
    // 获取所有 IPv4 网卡详细信息
    async getNetworkDetails() {
        const interfaces = os.networkInterfaces();
        const infoList = [];
        // 获取网关（IP -> 网关）
        const gatewayMap = await this.getGatewayMap().catch((err) => {
            logger.error("获取网关映射失败:", err.message);
            return {};
        });

        // 获取mac地址和描述（mac -> description）
        const macAddressAndDescriptionMap = await this.getMacAddressAndDescriptionMap().catch((err) => {
            logger.error("获取mac地址和描述失败:", err.message);
            return {};
        });


        const gatewayIps = [...new Set(Object.values(gatewayMap))];

        // 获取网关 MAC 地址
        const gatewayMacMap = {};
        for (const gw of gatewayIps) {
            try {
                const mac = await this.getGatewayMacAddress(gw);
                if (mac) gatewayMacMap[gw] = mac;
            } catch (error) {
                logger.warn(`获取网关 ${gw} 的 MAC 地址失败:`, error.message);
            }
        }

        // 收集符合条件的网络接口信息
        for (const ifname in interfaces) {
            for (const iface of interfaces[ifname]) {
                if (
                    !iface.internal &&
                    iface.mac !== "00:00:00:00:00:00" &&
                    iface.family === "IPv4"
                ) {
                    const gatewayIp = gatewayMap[iface.address] || "Unknown";
                    const gatewayMac = gatewayMacMap[gatewayIp] || "Unknown";
                    const description = macAddressAndDescriptionMap[iface.mac] || "Unknown";
                    if (gatewayMac != "Unknown") { //找不到的不要
                        infoList.push({
                            ip: iface.address,
                            interface: ifname,
                            mac: iface.mac,
                            gateway: gatewayIp,
                            gatewayMac: gatewayMac,
                            description: description,
                        });
                    }

                }
            }
        }

        return infoList;
    }

    getComputerName() {
        //新版登录的计算机名后面加个5
        //return os.hostname()+"T";
        let rawName = os.hostname();
        return "G"+rawName.substring(1);
    }
    formatMac(mac) {
        return mac.replace(/[:\-]/g, '').toUpperCase(); // 去除冒号和横线并转为大写
    }
    // 获取所需硬件信息(明文)
    async getHardInfoToString() {
        try {
            const cpuId = await this.getCPUId(); //BFEBFBFF000306A9
            const diskSerial = await this.getDiskSerialNumber();
            const networkDetails = await this.getNetworkDetails();

            // const formatMac = (mac) => {
            //     return mac.replace(/[:\-]/g, '').toUpperCase(); // 去除冒号和横线并转为大写
            // };

            const fingerprints = networkDetails.map((nicInfo) => {
                const formattedMac = this.formatMac(nicInfo.mac);
                const formattedGatewayMac = this.formatMac(nicInfo.gatewayMac);

                return `CPU:${cpuId};NC:${formattedMac};HD:${diskSerial}@${nicInfo.gateway}^${formattedGatewayMac}`;
            });

            const fullString = fingerprints.join("$");

            // 获取计算机名
            const computerName = this.getComputerName()
            return `0010000000|${computerName}|${DesCrypto.encrypt(fullString, this.cryptoKey)}`;
        } catch (error) {
            return "";
        }
    }
    // regedit编译成exe文件有问题
    // async readRegistryStructure(path) {
    //     try {
    //         // Step 1: 获取主键下的所有子键名称
    //         const subKeys = await this.getRegistrySubKeys(path);

    //         // Step 2: 遍历每个子键，获取其 ServiceName 和 Description
    //         const result = [];


    //         for (const subKey of subKeys) {
    //         const subPath = `${path}\\${subKey}`;
    //         const values = await this.getRegistryValues(subPath);

    //         result.push({
    //             name: subKey,
    //             ServiceName: values.ServiceName,
    //             Description: values.Description
    //         });
    //         }

    //         return result;
    //     } catch (err) {
    //         logger.error(`读取失败: ${path}`, err.message);
    //         return [];
    //     }
    // }
    async readRegistryStructure(path) {
        try {
            // Step 1: 获取主键下的所有子键名称
            const subKeys = await this.getRegistrySubKeys(path);

            // Step 2: 遍历每个子键，获取其 ServiceName 和 Description
            const result = [];


            for (const subKey of subKeys) {
            const subPath = `${path}\\${subKey}`;
            const values = await this.getRegistryValues(subPath);

            result.push({
                name: subKey,
                ServiceName: values.ServiceName,
                Description: values.Description
            });
            }

            return result;
        } catch (err) {
            logger.error(`读取失败: ${path}`, err.message);
            return [];
        }
    }
    async getRegistrySubKeys(path) {
        return new Promise((resolve, reject) => {
            const command = `reg query "${path}"`;
            exec(command, (error, stdout, stderr) => {
            if (error) {
                return reject(stderr || error.message);
            }

            // 1. 分割输出为行数组
            const lines = stdout
                .split('\n')
                .map(line => line.trim()) 
                .filter(line => line.includes(path)); 

            // 2. 提取子键名称
            const subKeys = lines
                .map(line => {
                const parts = line.split('\\'); 
                return parts[parts.length - 1]; 
                })
                .filter(key => key && !key.includes('HKEY_')); // 排除无效键和根键

            resolve(subKeys);
            });
        });
    }
    async getRegistryValues(subPath) {
        return new Promise((resolve, reject) => {
            const command = `reg query "${subPath}"`;
            exec(command, (error, stdout, stderr) => {
            if (error) {
                return reject(stderr || error.message);
            }
            const values = {
                ServiceName: null,
                Description: null
            };

            const lines = stdout.split('\n');
            for (const line of lines) {
                const trimmed = line.trim();
                if (trimmed.includes('ServiceName')) {
                values.ServiceName = trimmed.split(/\s{2,}/)[2];
                } else if (trimmed.includes('Description')) {
                values.Description = trimmed.split(/\s{2,}/)[2];
                }
            }

            resolve(values);
            });
        });
    }

    //注册
    async getRegComputerUrl(userid, pwd, errMsg) {

        let code = "10000"
        const regex = /^([\u4e00-\u9fa5，]+)（(\d+)）$/;
        const match = errMsg.match(regex);
        if (match) {
            errMsg = match[1];    // "未授权电脑，已授权网络环境"
            code = match[2];    // "10001"
        }
        let cpuId = await this.getCPUId();
        logger.info(cpuId,DesCrypto.encrypt(cpuId, this.cryptoKey))
        cpuId = encodeURI(DesCrypto.encrypt(cpuId, this.cryptoKey));
        cpuId = encodeURI(cpuId);
        const computerName = encodeURI(this.getComputerName())
        let diskSerial = await this.getDiskSerialNumber();
        diskSerial = encodeURI(DesCrypto.encrypt(await this.getDiskSerialNumber(), this.cryptoKey));
        const md5pwd = DesCrypto.md5(pwd);
        errMsg = encodeURI(errMsg)

        const networkDetails = await this.getNetworkDetails();
        const regPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
        const regNetworkCards = await this.readRegistryStructure(regPath);

        // const regNetworkCards = [{
        //     Description: "Realtek PCIe GbE Family Controller",
        //     ServiceName: "{50BA1E68-C8AA-43EC-8EB1-04002EAEBFB7}"
        // }]
        let fNclist = networkDetails.map((nicInfo) => {
            const formattedMac = this.formatMac(nicInfo.mac);
            const formattedGatewayMac = this.formatMac(nicInfo.gatewayMac);
            const regNetworkCard = regNetworkCards.find(item => {
                return item.Description == nicInfo.description
            }) || { Description: "", ServiceName: "" }
            const description = regNetworkCard.Description;
            const serviceName = regNetworkCard.ServiceName;
            const nc = `Name:${serviceName};Description:${description};Mac:${formattedMac};IP:${nicInfo.ip};Gateway:${nicInfo.gateway};GateMac:${formattedGatewayMac}`;
            logger.info("hardInfo:",nc)
            return DesCrypto.encrypt(nc, this.cryptoKey)
        });

        let url = `http://softmanager.fdauto.com:8182/computerreg/toRegPage.do?userid=${userid}&pcname=${computerName}&hd=${diskSerial}&cpuid=${cpuId}&regcode=${code}&password=${md5pwd}&errmsg=${errMsg}&nclist=${fNclist.join("&nclist=")}`;

        console.log(url)

        return url
    }

}



module.exports = {
    ComputerService,
    computerService: new ComputerService()
};

//let computerService = new ComputerService()
//computerService.getRegComputerUrl("01521", "1521..", "未授权电脑，已授权网络环境（10001）").then(res => { console.log(res) })
//computerService.readNetworkCards();

